/*
 * GiveTakeXMLConfigFileParameters.java
 *
 * Created on 29 de Março de 2010, 18:26
 *
 */

package intopo.game.impl.givetake;

import intopo.game.XMLConfigFileParameters;

import util.xml.*;

import cern.jet.random.engine.RandomEngine;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.HashMap;

/**
 *
 * @author <a href="mailto:plsm@ua.pt">Pedro Lopes da Silva Mariano</a>
 *
 * @version 1.0 29 de Março de 2010
 */
final public class GiveTakeXMLConfigFileParameters
	implements XMLConfigFileParameters<GiveTakeStrategy, GiveTakeGame>
{
	final private static String ROOT_NODE = "GiveTakeGame";

	final private static Map<String, Constructor<? extends GiveTakeStrategy>> STRATEGY_CONSTRUCTORS;
	
	final private static Map<String, Constructor<? extends GiveTakeGame>> GAME_CONSTRUCTORS;

	static
	{
		Constructor<? extends GiveTakeStrategy> cp;
		STRATEGY_CONSTRUCTORS = new HashMap<String, Constructor<? extends GiveTakeStrategy>> ();
		try {
			Class<GiveTakeProbabilisticStrategy> c = GiveTakeProbabilisticStrategy.class;
			cp = c.getConstructor (Element.class, RandomEngine.class);
			STRATEGY_CONSTRUCTORS.put ("GiveTakeProbabilisticPlayer", cp);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeProbabilisticPlayer does not have a constructor with parameter type org.w3c.dom.Element");
			System.exit (1);
		}
		try {
			Class<GiveTakeDeterministicStrategy> c = GiveTakeDeterministicStrategy.class;
			cp = c.getConstructor (Element.class, RandomEngine.class);
			STRATEGY_CONSTRUCTORS.put ("GiveTakeDeterministicPlayer", cp);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeDeterministicPlayer does not have a constructor with parameter type org.w3c.dom.Element");
			System.exit (1);
		}

		Constructor<GiveTakeGame> cg;
		GAME_CONSTRUCTORS = new HashMap<String, Constructor<? extends GiveTakeGame>> ();
		try {
			Class<GiveTakeGame> c = GiveTakeGame.class;
			cg = c.getConstructor (Element.class);
			GAME_CONSTRUCTORS.put ("GiveTakeGame", cg);
		}
		catch (NoSuchMethodException nsme) {
			System.err.println ("Class GiveTakeGame does not have a constructor with parameter type org.w3c.dom.Element");
			System.exit (1);
		}
	}

	/**
	 * Creates a new instance of GiveTakeXMLConfigFileParameters
	 */
	public GiveTakeXMLConfigFileParameters ()
{
	}

	public String getRootNodeName ()
	{
		return ROOT_NODE;
	}

	/**
	 * Return a map that associates tag names to game constructors. The XML file should only have a single tag whose name is a key of the returned map.
	 */
	public Map<String, Constructor<? extends GiveTakeGame>> getGameConstructor ()
	{
		return GAME_CONSTRUCTORS;
	}

	/**
	 * Return a map that associates tag names to strategy constructors.
	 */
	public Map<String, Constructor<? extends GiveTakeStrategy>> getStrategyConstructors ()
	{
		return STRATEGY_CONSTRUCTORS;
	}

	public void parse (Node rootNode)
		throws XMLParseException
	{
		AttributeParser<Integer> api;
		AttributeParser<Float> apf;
		
		api = new AttributeParser<Integer>
			(new CheckExistenceAttribute<Integer> (),
			 new ParseAsInt (0, Integer.MAX_VALUE));
		apf = new AttributeParser<Float>
			(new CheckExistenceAttribute<Float> (),
			 new ParseAsFloat (0, 1.0f));

		Node e1, e2;
		if ((e1 = XML.getChildNodeWithName (rootNode, "GiveTakeDeterministicPlayerParameters")) != null) {
			GiveTakeDeterministicStrategy.Parameters.giveIteration =
				api.parse ((Element) e1, "giveIteration");
			GiveTakeDeterministicStrategy.Parameters.takeIteration =
				api.parse ((Element) e1, "takeIteration");
			GiveTakeDeterministicStrategy.Parameters.binomialSuccess =
				apf.parse ((Element) e1, "binomialSuccess");
		}
		if ((e1 = XML.getChildNodeWithName (rootNode, "GiveTakeStochasticPlayerParameters")) != null) {
			GiveTakeProbabilisticStrategy.BinParameters.giveIteration =
				api.parse ((Element) e1, "giveIteration");
			GiveTakeProbabilisticStrategy.BinParameters.takeIteration =
				api.parse ((Element) e1, "takeIteration");
			GiveTakeProbabilisticStrategy.BinParameters.giveProbability =
				api.parse ((Element) e1, "giveProbability");
			GiveTakeProbabilisticStrategy.BinParameters.takeProbability =
				api.parse ((Element) e1, "takeProbability");
		}
	}
}
